using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.Runtime.CompilerServices;
using Atala = Atalasoft.Imaging;
using AtalaCodec = Atalasoft.Imaging.Codec;
using Dimok;

namespace Tiffer
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Implements methods to work with TIFF files. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class Tiff {
		const int pi = 1;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Resizes. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="image">		The image. </param>
		/// <param name="maxSize">	Size of the maximum. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static System.Drawing.Size Resize(byte[] image,int maxSize) {
			Atalasoft.Imaging.Workspace ws = new Atalasoft.Imaging.Workspace();
			ws.Open(new MemoryStream(image));
			ws.ApplyCommand(new Atalasoft.Imaging.ImageProcessing.ResampleCommand(maxSize));
			image = ws.Image.ToByteArray(new Atalasoft.Imaging.Codec.TiffEncoder());
			return new Size(ws.Image.Width,ws.Image.Height);
		}


		#region Tiff to PDF

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Tiif to pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">	The file. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] TiifToPDF(byte[] file){
			Atalasoft.Imaging.Workspace ws = new Atalasoft.Imaging.Workspace();
			ws.Open(new MemoryStream(file),0);
			MemoryStream ms = new MemoryStream();
			double ratio = ws.Image.Resolution.X/ws.Image.Resolution.Y;
			ws.Image.Resolution = new Atalasoft.Imaging.Dpi(200,200,Atala.ResolutionUnit.DotsPerInch);
			ws.Save(ms,new Atalasoft.Imaging.Codec.PdfEncoder(Atala.Codec.PdfPageSizeMode.FitToPage,new Size(ws.Image.Width, (int)Math.Round(ws.Image.Height*ratio,0)),0,new Atala.Codec.PdfMetadata()));
			return ms.ToArray();
		}
		#endregion
		#region ========================== DeletePages(...) ==============================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">				The file in. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string DeletePages(string fileIn, params int[] pageNumbers) {
			byte[] file = DeletePages(new Atala.ImageCollection(fileIn, null), pageNumbers).ToByteArray(AtalaCodecDefault, null);
			if (file.Length > 0)
				using (FileStream fs = File.Create(fileIn))
					fs.Write(file, 0, file.Length);
			else File.Delete(fileIn);
			return fileIn;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">					The file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] DeletePages(byte[] file, params int[] pageNumbers) {
			return DeletePages(new Atala.ImageCollection(new MemoryStream(file), null), pageNumbers).ToByteArray(AtalaCodecDefault, null);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="ic">						The ic. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static Atala.ImageCollection DeletePages(Atala.ImageCollection ic, params int[] pageNumbers) {
			ArrayList alImages = new ArrayList();
			foreach( int pageNumber in FileManager.MakePageNumbers(ic.Count,pageNumbers) )
				alImages.Add(ic[pageNumber-1]);
			foreach( Atala.AtalaImage image in alImages )
				ic.Remove(image);
			return ic;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">			The file in. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(string fileIn, int startPage){
			DeletePages(fileIn, startPage, -1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">			The file in. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(string fileIn, int startPage, int count){
			MemoryStream ms = new MemoryStream();
			if( UseAtalaSoft ){
				FileStream fsIn = File.OpenRead(fileIn);
				ms = DeletePages_AS(fsIn,startPage,count);
				fsIn.Close();
			}else
				DeletePages(ms,fileIn,startPage,count);
			FileStream fs = new FileStream(fileIn,FileMode.Create);
			ms.WriteTo(fs);
			fs.Close();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="fileIn">			The file in. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(string fileOut, string fileIn, int startPage){
			DeletePages(fileOut, fileIn, startPage, -1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="fileIn">			The file in. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(string fileOut, string fileIn, int startPage, int count){
			FileStream fs = new FileStream(fileOut,FileMode.Create);
			DeletePages(fs,fileIn,startPage,count);
			fs.Close();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="imageIn">		The image in. </param>
		/// <param name="startPage">	The start page. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] DeletePages(byte[] imageIn, int startPage){
			return DeletePages(imageIn,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="imageIn">		The image in. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] DeletePages(byte[] imageIn, int startPage, int count){
			if( imageIn == null && imageIn.Length == 0 )return new byte[]{};
			return DeletePages(new MemoryStream(imageIn),startPage,count).GetBuffer();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="fileIn">			The file in. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(Stream streamOut, string fileIn, int startPage){
			DeletePages(streamOut,fileIn,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="FileNotFoundException">	Thrown when the requested file is not present. </exception>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="fileIn">			The file in. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(Stream streamOut, string fileIn, int startPage, int count){
			FileInfo fi = new FileInfo(fileIn);
			if( !fi.Exists )throw new FileNotFoundException("File \""+fileIn+"\" not found",fileIn);
			if( fi.Length == 0 )throw new FileNotFoundException("File \""+fileIn+"\" is empty",fileIn);
			DeletePages(streamOut,new System.Drawing.Bitmap(fileIn),startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamIn">		The stream in. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream DeletePages(Stream streamIn, int startPage, int count){
			MemoryStream ms = new MemoryStream();
			DeletePages(ms,streamIn,startPage,count);
			return ms;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="streamIn">		The stream in. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(Stream streamOut, Stream streamIn, int startPage){
			DeletePages(streamOut,streamIn,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="ApplicationException">	Thrown when application. </exception>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="streamIn">		The stream in. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(Stream streamOut, Stream streamIn, int startPage, int count){
			if( streamIn.Length == 0 )throw new ApplicationException("Image stream is empty.");
			DeletePages(streamOut,new System.Drawing.Bitmap(streamIn),startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="bitMap">			The bit map. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(Stream streamOut, System.Drawing.Bitmap bitMap, int startPage){
			DeletePages(streamOut,bitMap, startPage, -1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="bitMap">			The bit map. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeletePages(Stream streamOut, System.Drawing.Bitmap bitMap, int startPage, int count){
			EncoderParameters encodeParams = InitEncodeParams();
			FrameDimension fd = new FrameDimension(bitMap.FrameDimensionsList[0]);
			int pageCount = bitMap.GetFrameCount(fd);
			int pageNumber,pageCounter=0;
			if( count == -1 )count = int.MaxValue;
			//Write pages before startPage
			for( pageNumber=0; pageNumber < startPage && pageNumber < pageCount; pageNumber++ )
				SaveFrame(pageCounter++,bitMap,streamOut,encodeParams,fd,pageNumber);
			//Skip pages after startPage
			for( ; pageNumber < startPage+count && pageNumber < pageCount; pageNumber++ ){}
			//Write pages after startPage+count
			for( ; pageNumber < pageCount; pageNumber++ )
				SaveFrame(pageCounter++,bitMap,streamOut,encodeParams,fd,pageNumber);
			//Flush
			if( pageCounter > 0 ){
				encodeParams.Param[pi] = new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.Flush);
				bitMap.SaveAdd(encodeParams);
				streamOut.Position = 0;
			}
			bitMap.Dispose();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages as. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">				The file. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static MemoryStream DeletePages_AS(Stream file,int startPage,int count){
			if( count <= 0 )count = int.MaxValue;
			Atala.Workspace wsFrom = new Atala.Workspace();
			MemoryStream streamTo = new MemoryStream();
			wsFrom.Open(file);
			for( int pageIndex = startPage; pageIndex < startPage+count && pageIndex < wsFrom.Images.Count; pageIndex++ )
				wsFrom.Images.RemoveAt(startPage);
			if( wsFrom.Images.Count > 0 )
				wsFrom.Save(streamTo,new AtalaCodec.TiffEncoder(AtalaCodec.TiffCompression.Group4FaxEncoding));
			streamTo.Position = 0;
			return streamTo;
		}
		#endregion =======================================================================

		#region ========================== AddPages(...) =================================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="imageFrom">	The image from. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="pageAfter">	The page after. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(byte[] imageFrom,string fileTo,int pageAfter){
			Atala.ImageCollection icFrom = new Atala.ImageCollection(new MemoryStream(imageFrom),null);
			Atala.ImageCollection icTo =
				File.Exists(fileTo) ? new Atala.ImageCollection(fileTo,null) : new Atala.ImageCollection();
			foreach( Atala.AtalaImage image in icFrom )
				icTo.Insert(pageAfter++,image);
			icTo.Save(fileTo,AtalaCodec.ImageType.Tiff,null);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">			The file to. </param>
		/// <param name="imageFrom">	The image from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileTo,byte[] imageFrom,int pageAfter,int startPage,int count){
			if( imageFrom == null || imageFrom.Length == 0 )return;
			MemoryStream ms = new MemoryStream(imageFrom);
			AddPages(fileTo,ms,pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">			The file to. </param>
		/// <param name="streamFrom">	The stream from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileTo,Stream streamFrom,int pageAfter,int startPage,int count){
			System.Drawing.Bitmap bm = new System.Drawing.Bitmap(streamFrom);
			AddPages(fileTo,bm,pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">			The file to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileTo,string fileFrom,int pageAfter,int startPage){
			AddPages(fileTo,fileTo,fileFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">			The file to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileTo,string fileFrom,int pageAfter,int startPage,int count){
			AddPages(fileTo,fileTo,fileFrom,pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">			The file to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage){
			AddPages(fileTo,fileTo,bmFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">			The file to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage,int count){
			AddPages(fileTo,fileTo,bmFrom,pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileOut,string fileTo,string fileFrom,int pageAfter,int startPage){
			AddPages(fileOut,fileTo,fileFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileOut,string fileTo,string fileFrom,int pageAfter,int startPage,int count){
			AddPages(fileOut,fileTo,new System.Drawing.Bitmap(fileFrom),pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileOut,string fileTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage){
			AddPages(fileOut,fileTo,bmFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileOut,string fileTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage,int count){
			if( !File.Exists(fileTo) || new FileInfo(fileTo).Length == 0 ){
				byte[] image = GetPages(bmFrom,startPage,count);
				FileStream fs = new FileStream(fileOut,FileMode.Create);
				fs.Write(image,0,image.Length);
				fs.Close();
			}else
				AddPages(fileOut,new System.Drawing.Bitmap(fileTo),bmFrom,pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="bmTo">				The bm to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileOut,System.Drawing.Bitmap bmTo,string fileFrom,int pageAfter,int startPage){
			AddPages(fileOut,bmTo,fileFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="bmTo">				The bm to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileOut,System.Drawing.Bitmap bmTo,string fileFrom,int pageAfter,int startPage,int count){
			AddPages(fileOut,bmTo,new System.Drawing.Bitmap(fileFrom),pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(Stream streamOut,string fileTo,string fileFrom,int pageAfter,int startPage){
			AddPages(streamOut,fileTo,fileFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(Stream streamOut,string fileTo,string fileFrom,int pageAfter,int startPage,int count){
			AddPages(streamOut,new System.Drawing.Bitmap(fileTo),new System.Drawing.Bitmap(fileFrom),pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(Stream streamOut,string fileTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage){
			AddPages(streamOut,fileTo,bmFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="fileTo">			The file to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(Stream streamOut,string fileTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage,int count){
			AddPages(streamOut,new System.Drawing.Bitmap(fileTo),bmFrom,pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="bmTo">				The bm to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(Stream streamOut,System.Drawing.Bitmap bmTo,string fileFrom,int pageAfter,int startPage){
			AddPages(streamOut,bmTo,fileFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="bmTo">				The bm to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(Stream streamOut,System.Drawing.Bitmap bmTo,string fileFrom,int pageAfter,int startPage,int count){
			AddPages(streamOut,bmTo,new System.Drawing.Bitmap(fileFrom),pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="bmTo">				The bm to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileOut,System.Drawing.Bitmap bmTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage){
			AddPages(fileOut,bmTo,bmFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileOut">		The file out. </param>
		/// <param name="bmTo">				The bm to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileOut,System.Drawing.Bitmap bmTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage,int count){
			MemoryStream ms = new MemoryStream();
			AddPages(ms,bmTo,bmFrom,pageAfter,startPage,count);
			FileStream fs = new FileStream(fileOut,FileMode.Create);
			ms.WriteTo(fs);
			fs.Flush();
			fs.Close();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="bmTo">				The bm to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(Stream streamOut,System.Drawing.Bitmap bmTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage){
			AddPages(streamOut,bmTo,bmFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="imgTo">			The image to. </param>
		/// <param name="imgFrom">		The image from. </param>
		/// <param name="pageAfter">	The page after. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPages(byte[] imgTo,byte[] imgFrom,int pageAfter){
			return AddPages(imgTo,imgFrom,pageAfter,0,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="imgTo">			The image to. </param>
		/// <param name="imgFrom">		The image from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPages(byte[] imgTo,byte[] imgFrom,int pageAfter,int startPage){
			return AddPages(imgTo,imgFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="imgTo">			The image to. </param>
		/// <param name="imgFrom">		The image from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPages(byte[] imgTo,byte[] imgFrom,int pageAfter,int startPage,int count){
			return AddPages(new MemoryStream(imgTo),new MemoryStream(imgFrom),pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamTo">		The stream to. </param>
		/// <param name="streamFrom">	The stream from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPages(Stream streamTo,Stream streamFrom,int pageAfter,int startPage){
			return AddPages(streamTo,streamFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamTo">		The stream to. </param>
		/// <param name="streamFrom">	The stream from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPages(Stream streamTo,Stream streamFrom,int pageAfter,int startPage,int count){
			if( UseAtalaSoft )
				return AddPagesEx(streamTo,streamFrom,pageAfter,startPage,count);
			return AddPages(streamTo,new System.Drawing.Bitmap(streamFrom),pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamTo">		The stream to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPages(Stream streamTo,string fileFrom,int pageAfter,int startPage){
			return AddPages(streamTo,fileFrom,pageAfter,startPage,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamTo">		The stream to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPages(Stream streamTo,string fileFrom,int pageAfter,int startPage,int count){
			return AddPages(streamTo,new System.Drawing.Bitmap(fileFrom),pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamTo">		The stream to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPages(Stream streamTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage,int count){
			MemoryStream ms = new MemoryStream();
			AddPages(ms,new System.Drawing.Bitmap(streamTo),bmFrom,pageAfter,startPage,count);
			return ms;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamOut">	The stream out. </param>
		/// <param name="bmTo">				The bm to. </param>
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(Stream streamOut,System.Drawing.Bitmap bmTo,System.Drawing.Bitmap bmFrom,int pageAfter,int startPage,int count){
			EncoderParameters encodeParams = InitEncodeParams();
			FrameDimension fdTo = new FrameDimension(bmTo.FrameDimensionsList[0]);
			FrameDimension fdFrom = new FrameDimension(bmFrom.FrameDimensionsList[0]);
			int pageCountTo = bmTo.GetFrameCount(fdTo);
			int pageCountFrom = bmFrom.GetFrameCount(fdFrom);
			if( pageAfter > pageCountTo )pageAfter = pageCountTo - 1;
			if( count <= 0 )count = int.MaxValue;
			int pageNumber,pageCounter=0;
			System.Drawing.Bitmap bmMain = bmTo;
			//Write pages before startPage
			for( pageNumber=0; pageNumber <= pageAfter  && pageNumber < pageCountTo; pageNumber++ )
				SaveFrame(pageCounter++,bmMain,streamOut,encodeParams,fdTo,pageNumber);
			if( pageCounter == 0 )bmMain = bmFrom;
			//Add pages after startPage
			for( pageNumber = startPage; pageNumber < startPage+count && pageNumber < pageCountFrom; pageNumber++ )
				SaveFrame(pageCounter++,bmMain,bmFrom,streamOut,encodeParams,fdFrom,pageNumber);
			//Add the rest from bmTo
			for( pageNumber = pageAfter+1; pageNumber < pageCountTo; pageNumber++ )
				SaveFrame(pageCounter++,bmMain,bmTo,streamOut,encodeParams,fdTo,pageNumber);
			bmTo.Dispose();
			bmFrom.Dispose();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// [pageAfter] must be -1 in order to add to the very beginning of image, [count] must be less
		/// then 1 to copy from startPage to the end. 
		/// </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">				The file to. </param>
		/// <param name="fileFrom">			The file from. </param>
		/// <param name="pageAfter">		The page after. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] AddPages(byte[] fileTo, byte[] fileFrom, int pageAfter, params int[] pageNumbers) {
			byte[][] pagesTo = SliceTiff(fileTo);
			List<byte[]> lstTo = pagesTo == null ? new List<byte[]>() : new List<byte[]>(pagesTo);
			lstTo.InsertRange(pageAfter, SliceTiff(fileFrom, pageNumbers));
			return JoinPages(lstTo.ToArray());
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Adds the pages ex. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamTo">		The stream to. </param>
		/// <param name="streamFrom">	The stream from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MemoryStream AddPagesEx(Stream streamTo,Stream streamFrom,int pageAfter,int startPage,int count) {
			Atala.Workspace wsFrom = new Atala.Workspace();
			Atala.Workspace wsOut = new Atala.Workspace();
			streamFrom.Position = 0;
			wsFrom.Open(streamFrom);
			streamTo.Position = 0;
			wsOut.Open(streamTo);
			for(int pageNumber = startPage; pageNumber < startPage+count && pageNumber < wsFrom.Images.Count; pageNumber++)
				wsOut.Images.Insert(++pageAfter,wsFrom.Images[pageNumber]);
			MemoryStream streamOut = new MemoryStream();
			wsOut.Save(streamOut,new AtalaCodec.TiffEncoder(AtalaCodec.TiffCompression.Group4FaxEncoding));
			return streamOut;
		}
		#endregion ===================================================================================

		#region ========================== GetPages(...) =================================
			#region ================= AtalaSoft ==================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the pages as. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">					The file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The pages as. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] GetPages_AS(byte[] file,params int[] pageNumbers){
			if( FileManager.IsAllPages(pageNumbers) )return file;
 			if( pageNumbers.Length == 1 && pageNumbers[0] >= 0 ){
 				Bitmap pic = new Bitmap(new MemoryStream(file));
 				pic.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, pageNumbers[0]-1);
 				MemoryStream msFile = new MemoryStream();
 				pic.Save(msFile, GetTiffEncoderInfo(), InitEncodeParams());
 				return msFile.ToArray();
 			}
			Atala.ImageCollection icIn = new Atalasoft.Imaging.ImageCollection(new MemoryStream(file),null);
			Atala.ImageCollection icOut = new Atalasoft.Imaging.ImageCollection();
			foreach( int pageNumber in FileManager.MakePageNumbers(icIn.Count,pageNumbers) )
				icOut.Add(icIn[pageNumber-1]);
			return icOut.ToByteArray(AtalaCodecDefault,null);
		}
			#endregion
		// public static byte[] GetPage(System.Drawing.Bitmap bmFrom,int pageNumber){
		// 	return GetPages(bmFrom,pageNumber,1);
		// }
		// public static byte[] GetPage(string fileName,int pageNumber){return GetPages(fileName,
		// pageNumber,1);} 
		public static byte[] GetPages(string fileName,params int[] pageNumbers){
			return GetPages(FileManager.GetBytesFromFile(fileName),pageNumbers);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get pages from [startPage] to the end ([count]=0) </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="file">					The file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] GetPages(byte[] file,params int[] pageNumbers){
			if( FileManager.IsAllPages(pageNumbers) )return file;
			if( UseAtalaSoft )return GetPages_AS(file,pageNumbers);
			throw new Exception("Unspecified TIFF Tool!");
		}
			#region GePages OLD

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get pages from [startPage] to the end ([count]=0) </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="image">			The image. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] GetPages(Stream image,int startPage,int count){
			return GetPages(new System.Drawing.Bitmap(image),startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get all pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="bmFrom">	The bm from. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static byte[] GetPages(System.Drawing.Bitmap bmFrom){
			return GetPages(bmFrom,0);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get pages from [startPage] to the end ([count]=0) </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="startPage">	The start page. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static byte[] GetPages(System.Drawing.Bitmap bmFrom,int startPage){
			return GetPages(bmFrom,startPage,0);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get pages from [startPage] to the end ([count]=0) </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="ApplicationException">	Thrown when application. </exception>
		/// <exception cref="Exception">						Thrown when exception. </exception>
		///
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static byte[] GetPages(System.Drawing.Bitmap bmFrom,int startPage,int count){
			try{
				MemoryStream streamOut = new MemoryStream();
				EncoderParameters encodeParams = InitEncodeParams();
				FrameDimension fdFrom = new FrameDimension(bmFrom.FrameDimensionsList[0]);
				int pageCountFrom = bmFrom.GetFrameCount(fdFrom);
				if( startPage >= pageCountFrom )throw new ApplicationException("Image does not have page #"+startPage+".");
				if( count <= 0 )count = int.MaxValue/2;
				int pageNumber,pageCounter=0;
				//Add pages after startPage
				for( pageNumber = startPage; pageNumber < startPage+count && pageNumber < pageCountFrom; pageNumber++ )
					SaveFrame(pageCounter++,bmFrom,streamOut,encodeParams,fdFrom,pageNumber);
				bmFrom.Dispose();
				byte[] b = new byte[streamOut.Length];
				streamOut.Position = 0;
				streamOut.Read(b,0,b.Length);
				return b;
			}catch( System.Exception exp ){
				throw new System.Exception("\nStart page:"+startPage+", count:"+count+"\n",exp);
			}
		}
			#endregion
		#endregion ========================================================================

		#region ========================== MovePages(...) ================================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileFrom">			The file from. </param>
		/// <param name="fileTo">				The file to. </param>
		/// <param name="pageAfter">		The page after. </param>
		/// <param name="copy">					true to copy. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void MovePages(string fileFrom,string fileTo,int pageAfter,bool copy,params int[] pageNumbers){
			Atala.ImageCollection icFrom = new Atala.ImageCollection(fileFrom,null);
			Atala.ImageCollection icTo =
				File.Exists(fileTo) ? new Atala.ImageCollection(fileTo,null) : new Atala.ImageCollection();
			MovePages(icFrom,icTo,pageAfter,copy,pageNumbers);
			if( !copy ){
				if( icFrom.Count > 0 )icFrom.Save(fileFrom,AtalaCodec.ImageType.Tiff,null);
				else File.Delete(fileFrom);
			}
			icTo.Save(fileTo,AtalaCodec.ImageType.Tiff,null);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="icFrom">				The ic from. </param>
		/// <param name="icTo">					The ic to. </param>
		/// <param name="pageAfter">		The page after. </param>
		/// <param name="copy">					true to copy. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static void MovePages(Atala.ImageCollection icFrom,Atala.ImageCollection icTo,int pageAfter,bool copy,params int[] pageNumbers){
			ArrayList alImages = new ArrayList();
			foreach( int pageNumber in FileManager.MakePageNumbers(icFrom.Count,pageNumbers) )
				icTo.Insert(pageAfter++,icFrom[pageNumber-1]);
			if( !copy )DeletePages(icFrom,pageNumbers);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="image">			The image. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="pageStart">	The page start. </param>
		/// <param name="pageCount">	Number of pages. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] MovePages(byte[] image,int pageAfter,int pageStart,int pageCount) {
			return ((MemoryStream)MovePages(new MemoryStream(image),pageAfter,pageStart,pageCount)).ToArray();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamIn">		The stream in. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="pageCount">	Number of pages. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Stream MovePages(Stream streamIn,int pageAfter,int startPage,int pageCount){
			return MovePages(new System.Drawing.Bitmap(streamIn),pageAfter,startPage,pageCount);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="ApplicationException">	Thrown when application. </exception>
		///
		/// <param name="bmFrom">			The bm from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Stream MovePages(System.Drawing.Bitmap bmFrom,int pageAfter,int startPage,int count){
			MemoryStream streamOut = new MemoryStream();
			EncoderParameters encodeParams = InitEncodeParams();
			FrameDimension fdFrom = new FrameDimension(bmFrom.FrameDimensionsList[0]);
			int pageCountFrom = bmFrom.GetFrameCount(fdFrom);
			if( startPage >= pageCountFrom )throw new ApplicationException("Image does not have page #"+startPage+".");
			if( count <= 0 )count = int.MaxValue;
			int pageNumber,pageCounter=0;
			//Write pages before pageAfter
			for( pageNumber=0; pageNumber <= pageAfter  && pageNumber < pageCountFrom; pageNumber++ )
				if( pageNumber < startPage || pageNumber >= startPage+count )
					SaveFrame(pageCounter++,bmFrom,streamOut,encodeParams,fdFrom,pageNumber);
			//Add pages after startPage
			for( pageNumber = startPage; pageNumber < startPage+count && pageNumber < pageCountFrom; pageNumber++ )
				SaveFrame(pageCounter++,bmFrom,streamOut,encodeParams,fdFrom,pageNumber);
			//Add pages after pageAfter
			for( pageNumber = pageAfter+1; pageNumber < pageCountFrom; pageNumber++ )
				if( pageNumber < startPage || pageNumber >= startPage+count )
					SaveFrame(pageCounter++,bmFrom,streamOut,encodeParams,fdFrom,pageNumber);
			bmFrom.Dispose();
			return streamOut;
		}
		#endregion =======================================================================

		#region ========================== PageCount(..) =================================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Page count. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="image">	The image. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static int PageCount(byte[] image) {
			if( image == null || image.Length == 0 )return 0;
			//if( UseAtalaSoft )return new Atalasoft.Imaging.ImageCollection(new MemoryStream(image),null).Count;
			return PageCount(new MemoryStream(image));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Page count. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="stream">	The stream. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static int PageCount(Stream stream){
			return PageCount(new System.Drawing.Bitmap(stream));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Page count. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">	Filename of the file. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static int PageCount(string fileName){
			try{
				try {
					if (UseAtalaSoft) return new Atalasoft.Imaging.ImageCollection(fileName, null).Count;
				} catch { }
				FileInfo f = new FileInfo(fileName);
				if( f.Length == 0 )return 0;
				return PageCount(new System.Drawing.Bitmap(fileName));
			}catch(System.Exception exc){ throw new System.Exception("\nFileName:"+fileName+"\n",exc); }
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Page count. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="bitMap">	The bit map. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static int PageCount(System.Drawing.Bitmap bitMap){
			FrameDimension fd = new FrameDimension(bitMap.FrameDimensionsList[0]);
			int pageCount = bitMap.GetFrameCount(fd);
			bitMap.Dispose();
			GC.Collect();
			return pageCount;
		}
		#endregion =======================================================================

		#region ========================== Helpers =======================================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Saves a frame. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pageCounter">	The page counter. </param>
		/// <param name="bm">						The bm. </param>
		/// <param name="strm">					The strm. </param>
		/// <param name="eps">					The eps. </param>
		/// <param name="fd">						The fd. </param>
		/// <param name="pageNumber">		The page number. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static void SaveFrame(int pageCounter,System.Drawing.Bitmap bm,Stream strm,EncoderParameters eps,FrameDimension fd,int pageNumber){
			SaveFrame(pageCounter,bm,bm,strm,eps,fd,pageNumber);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Saves a frame. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pageCounter">	The page counter. </param>
		/// <param name="bmTo">					The bm to. </param>
		/// <param name="bmFrom">				The bm from. </param>
		/// <param name="strm">					The strm. </param>
		/// <param name="eps">					The eps. </param>
		/// <param name="fd">						The fd. </param>
		/// <param name="pageNumber">		The page number. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static void SaveFrame(int pageCounter,System.Drawing.Bitmap bmTo,System.Drawing.Bitmap bmFrom,Stream strm,EncoderParameters eps,FrameDimension fd,int pageNumber){
			bmFrom.SelectActiveFrame(fd,pageNumber);
			if( pageCounter == 0 )bmTo.Save(strm,GetTiffEncoderInfo(),eps);
			else{
				eps.Param[pi] = new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.FrameDimensionPage);
				bmTo.SaveAdd(bmFrom,eps);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Initialises the encode parameters. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static EncoderParameters InitEncodeParams(){
			EncoderParameters eps = new EncoderParameters(2);
			eps.Param[pi] = new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.MultiFrame);
			eps.Param[0] = new EncoderParameter(Encoder.Compression,(long)EncoderValue.CompressionCCITT4); 
			//GetCompressionParam(bitMap.GetEncoderParameterList(GetTiffEncoderInfo().Clsid)).;
			//encodeParams.Param[0] = GetCompressionParam(bitMap.GetEncoderParameterList(GetTiffEncoderInfo().Clsid));
			return eps;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a compression parameter. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="eps">	The eps. </param>
		///
		/// <returns>	The compression parameter. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static EncoderParameter GetCompressionParam(EncoderParameters eps){
			for( int i=0; i < eps.Param.Length; i++ )
				if( eps.Param[i].Encoder.Guid == Encoder.Compression.Guid )
					return eps.Param[i];
			return null;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the tiff encoder information. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The tiff encoder information. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static ImageCodecInfo GetTiffEncoderInfo() {
			int j;
			ImageCodecInfo[] encoders;
			encoders = ImageCodecInfo.GetImageEncoders();
			for(j = 0; j < encoders.Length; ++j) {
				if(encoders[j].MimeType == "image/tiff")
					return encoders[j];
			}
			return null;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the temp file name. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The temp file name. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetTempFileName()
		{
			return DateTime.Now.ToString("fffffff");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a value indicating whether this object use atala soft. </summary>
		///
		/// <value>	true if use atala soft, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static bool UseAtalaSoft{get{return ConfigurationSettings.AppSettings["atalasoft"] == "true";}}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the version. </summary>
		///
		/// <value>	The version. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string version
		{
			get
			{
				return Assembly.GetAssembly(System.Type.GetType("Tiffer.Tiff")).GetName().Version.ToString();
			}
		}
		#endregion ======================================================================
		
		#region========================== SliceTiff(...) ================================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Slice ex. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="streamFrom">		The stream from. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] SliceEx(Stream streamFrom,params int[] pageNumbers){
			if( streamFrom == null || streamFrom.Length == 0 )return null;
			Atala.ImageCollection icFrom = new Atalasoft.Imaging.ImageCollection(streamFrom,null);
			ArrayListEx alImages = new ArrayListEx();
			foreach( int pageNumber in FileManager.MakePageNumbers(icFrom.Count,pageNumbers) )
				alImages.Add(icFrom[pageNumber-1].ToByteArray(AtalaCodecDefault));
			return alImages;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Slice tiff. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="FileNotFoundException">	Thrown when the requested file is not present. </exception>
		///
		/// <param name="fileIn">	The file in. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string[] SliceTiff(string fileIn){
			if(!File.Exists(fileIn)) throw new FileNotFoundException("File "+fileIn+" cannot be not found.",fileIn);
			int pageCount = PageCount(fileIn);
			string[] pages = new string[pageCount];
			for(int i=0;i<pageCount;i++){
				string p = (i+1).ToString("000");
				string newFile = fileIn.Replace(".","_"+p+".");
				pages[i] = newFile;
				AddPages(newFile,fileIn,i,i,1);
			}
			return pages;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Slices the given file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	Filename of the file. </param>
		/// <param name="dirOut">		The dir out. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string Slice(string fileName,string dirOut){
			if( !Directory.Exists(dirOut) )Directory.CreateDirectory(dirOut);
			else FileManager.DeleteFiles(dirOut);
			string fileOut = FileManager.GetFileFromBytes(new byte[]{},Path.Combine(dirOut,"Page.tif"),true);
			try{
				byte[][] pages = SliceTiff(FileManager.GetBytesFromFile(fileName));
				foreach( byte[] page in pages )
					FileManager.GetFileFromBytes(page,fileOut,true);
				return dirOut;
			}finally{
				File.Delete(fileOut);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Slice tiff. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">					The file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] SliceTiff(byte[] file,params int[] pageNumbers){
			//if( UseAtalaSoft )
			//return SliceEx(file == null? null : new MemoryStream(file),pageNumbers);
			List<byte[]> pages = new List<byte[]>();
			foreach (int i in FileManager.MakePageNumbers(PageCount(file), pageNumbers))
				pages.Add(GetPages(new MemoryStream(file), i-1, 1));
			return pages.ToArray();
		}
		#endregion =======================================================================

		#region ========================== CombineFolder(...) ============================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Join pages ex. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pages">	Array of Pages. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] JoinPagesEx(byte[][] pages) {
			Atala.Workspace wsOut = new Atala.Workspace();
			ArrayList alWsOuts = new ArrayList();
			foreach( byte[] page in pages ){
				Atala.Workspace wsPage = new Atala.Workspace();
				wsPage.Open(new MemoryStream(page));
				wsOut.Images.Add(wsPage.Images[0]);
				alWsOuts.Add(wsPage);
			}
			MemoryStream streamOut = new MemoryStream();
			wsOut.Save(streamOut,new AtalaCodec.TiffEncoder(AtalaCodec.TiffCompression.Group4FaxEncoding));
			return streamOut.ToArray();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Join array of pages to multipage file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pages">	Array of Pages. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] JoinPages(byte[][] pages){
			if( UseAtalaSoft )return JoinPagesEx(pages);
			if(pages == null || pages.Length == 0) return new byte[0];
			MemoryStream ms = new MemoryStream(pages[0]);
			for(int i=1;i<pages.Length;i++)
				ms = AddPages(ms,new MemoryStream(pages[i]),i-1,0);
			return ms.ToArray();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combines array of pages in one file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="rows">	The first field (column) in rows collection must contain file in bytes
		/// 										array. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] JoinPages(DataRowCollection rows){
			if( ConfigurationSettings.AppSettings["atalasoft"] == "true" )
				return JoinPagesEx(GetPagesFromRows(rows));
			if(rows.Count == 0) return new byte[0];
			MemoryStream ms = new MemoryStream((byte[])rows[0]["Data"]);
			for(int i=1;i<rows.Count;i++)
				ms = AddPages(ms,new MemoryStream((byte[])rows[i]["Data"]),i-1,0);
			return ms.ToArray();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the pages from rows. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="rows">	The first field (column) in rows collection must contain file in bytes
		/// 										array. </param>
		///
		/// <returns>	The pages from rows. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static byte[][] GetPagesFromRows( DataRowCollection rows ){
			ArrayList alBytes = new ArrayList();
			foreach( DataRow row in rows )
				alBytes.Add((byte[])row["Data"]);
			return (byte[][])alBytes.ToArray(typeof(byte[]));
		}
		#endregion =======================================================================

		#region ==================== Atalasoft Helpers =====================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the atala codec default. </summary>
		///
		/// <value>	The atala codec default. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static AtalaCodec.TiffEncoder AtalaCodecDefault{get{return new AtalaCodec.TiffEncoder(AtalaCodec.TiffCompression.Group4FaxEncoding);}}
		#endregion
	}
}